iT邦幫忙

DAY 16
0

Ruby女孩:10萬.times { puts "為什麼?" }系列 第 16

Ruby女孩(16):物件之間相等性的比較

  • 分享至 

  • xImage
  •  

※ 物件類別與物件型別
我們曾在前面的文章中提及,如果我需要知道某物件是什麼類別,我們可以用.class,如果我們想知道它的父類別可以用.superclass,如果想列出它的祖先們,可以用.ancestors,不過Ruby其實也有更優雅的寫法XD,以前不知道優雅是什麼,不過我想,就是更人性的方式吧,大家來看看:

普通的比較

"oh my god!".class == String
=> true

優雅優雅優雅優雅優雅的寫法

"oh my god!".instance_of? String
=> true

但這有個問題,當我寫:

"oh my god!".instance_of? Object
=> false

阿不是一直強調Ruby中萬事萬物都是物件嗎?怎麼會是錯的?

原來這 .class 和 .instance_of? 是不會查到該類別的所有父類別,如果想要查到父類別,就要使用 .is_a? 這個方法,例如:

xxx = 5566
xxx.instance_of? Fixnum
=> true

xxx.is_a? Fixnum
=> true

xxx.is_a? Integer
=> true

xxx.is_a? Numeric
=> true

xxx.is_a? Object
=> true

『Ruby中,每個物件都會具有一個定義明確的類別,而且該類別絕不會在物件存活期間遭到改變。』(p.79)

阿勒?類別不會改變嗎?看到這句疑惑了一下,想說我們先前不是才學到可以to_i、to_s、to_sym等方法可以改變物件類別嗎?
所以測試了一下:

x = "annie"
x.class  => String
x.object_id  => 70148984557260
y = x.to_sym  => :annie
y.object_id  => 657928
x.object_id  => 70148984557260

可以看到我確實把x指向的物件"annie"變成symbol,但這個symbol物件會存到另一個記憶體位置,變成新的物件!再回頭去看x,其實這個物件本身是沒有被改變的!

※ 物件的相等性

Ruby提供了一些驚奇的做法來判斷物件是否相等!這地方我覺得非常重要,了解運算規則後,做邏輯判斷才不會用錯方法!

1. equal?
這個方法判斷兩個值是否指向相同的物件!例如:

a = "Ruby"
b = c = "Ruby"
a.equal? b  => false
b.equal? c  => true

其實.equal?這個方法就是在檢查兩邊所指向的object_id是否一樣!

2. ==
這個方法是在判斷兩邊值的相等性!例如:

a = "Ruby"
b = "Ruby"
a.equal? b  => false
a == b  => true

c = [1,3,5]
d = [1,3,5]
e = [1,5,3]
c == d  => true
c == e  => false

雖然a、b所指向的物件不同,但是兩物件有相同的值,因此做==判斷是true。而c、d、e指向的陣列都是不同物件,但c和d的值完全相等(順序也一樣),所以相等性判斷為true。反之,e與c、d的值順序不同,相等性判斷就為false。

值得一提的是,Numeric類別中的數,在做相等性判斷時,會自動進行型別轉換,例如:

1 == 1.0  => true

雖然一個是Fixnum、一個是Float,但他很聰明可以判斷這值是相等的!

若要比較範圍和陣列的相等性的話,我們也可以這麼做:

(1..3).to_a == [1,2,3]  => true
# 先把一邊轉換,再做比較,此時只看值的話,相等性判斷為true

(1..3).to_a.equal? [1,2,3]  => false
# 但別忘了,他還是不同的物件喔!

有相等就有不等,!=(不等於)是拿來測不等性,其實在Ruby的實作中,當他看到!=,只會使用==來判斷是否相等,然後直接把結果反轉,來當作!=的結果。

3. eql?
如果說 == 是好好先生,那 .eql? 可以說是嚴格的大叔,相較於==,.eql?不會進行型別轉換,我們來看看:

1 == 1.0  => true
1.eql? 1.0  => false

"Ruby".eql? "Ruby"  => true

可以看到,不同物件中的值只要一樣,.eql?的判斷依舊會成真,但是型別不同時,他是不會自己幫你判斷的!

4. ===
==是測值的相等性,而===是測情況相等性(case equality),直接來看看例子:

(1..10) === 5  => true
# 範圍是測試值有沒有落在區間中

/\d+/ === "123"  => true
# 正規表達式是測試字串是否符合正規表達式

String === "ya"  => true
# 類別會判斷某物件是不是該類別的實例

:ss === "ss"  => true
# Symbol除了判斷左右兩邊是不是相同的符號,如果右邊是字串,他會判斷字串的內容是不是跟自己一樣,是的話也會回傳true!

不過書中說上面這幾種述句不常見,比較常見的是用在case數據的用法,第五章才會提到,我們之後再揭曉!

5. =~

前面幾種方法都是定義於Object,只有現在這個=~方法是定義在String、Regexp中(也包含Symbol),他所進行的是樣式比對運算。這個部分書上沒有舉例子,我們可以參考此文件最下方的例子,以及此份文件有更完整的說明

這個方法會需要理解正規表達式之後,才能更清楚他的做法。

=================================================

16天,

“You can feel sore tomorrow or you can feel sorry tomorrow. You choose.”

未來怎麼樣,都看你今天決定做了什麼,我今天沒看到想要的進度,所以明天一定是感到sorry哭哭


上一篇
Ruby女孩(15):Ruby物件的生與死
下一篇
Ruby女孩(17):自己做排序的方法!
系列文
Ruby女孩:10萬.times { puts "為什麼?" }30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言